﻿// MIT License (MIT)
// 
// Copyright (c) 2014 K Ercan Turkarslan
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// 

using System;

namespace MiosGenerator
{
    public class UpnpDataType
    {
        public String CSharp { get; private set; }
        public Boolean IsString { get; private set; }
        public Boolean IsNumeric { get; private set; }

        #region ReadOnly Property Upnp : String;
        private String ToCSharp()
        {
            switch (Upnp)
            {
                case "string": return "String";
                case "boolean": return "Boolean";
                case "i1": return "SByte";
                case "ui1": return "Byte";
                case "i2": return "Int16";
                case "ui2": return "UInt16";
                case "i4": return "Int32";
                case "int": return "Int32";
                case "ui4": return "UInt32";
                case "dateTime": return "DateTime";
                default:
                    throw new ArgumentOutOfRangeException(String.Format("[{0}] is not a handled type!", Upnp));
            }
        }

        private String _upnp;

        public String Upnp
        {
            get { return _upnp; }
            private set
            {
                if (!IsUpnpType(value))
                    throw new InvalidOperationException("Supported UPNP type expected!");

                _upnp = value;

                CSharp = ToCSharp();
                IsString = (CSharp == "String");

                IsNumeric = false;
                switch (Upnp)
                {
                    case "i1":
                    case "ui1":
                    case "i2":
                    case "ui2":
                    case "i4":
                    case "int":
                    case "ui4":
                        IsNumeric = true;
                        break;
                }
            }

        }

        #endregion

        #region ReadOnly Property NullableType : String;
        private readonly String _nullableType = null;

        private String ToNullable()
        {
            return String.Format("{0}{1}", CSharp, IsString ? "" : "?");
        }

        internal String Nullable
        {
            get { return _nullableType ?? ToNullable(); }
        }
        #endregion

        public Boolean IsMinValue(String value)
        {
            try
            {
                switch (Upnp)
                {
                    case "i1":
                        return SByte.Parse(value) == SByte.MinValue;
                    case "ui1":
                        return Byte.Parse(value) == Byte.MinValue;
                    case "i2":
                        return Int16.Parse(value) == Int16.MinValue;
                    case "ui2":
                        return UInt16.Parse(value) == UInt16.MinValue;
                    case "int":
                    case "i4":
                        return Int32.Parse(value) == Int32.MinValue;
                    case "ui4":
                        return UInt32.Parse(value) == UInt32.MinValue;
                }
            }
            catch (OverflowException)
            {

            }
            catch (FormatException)
            {

            }

            return false;
        }

        public Boolean IsMaxValue(String value)
        {
            try
            {
                switch (Upnp)
                {
                    case "i1":
                        return SByte.Parse(value) == SByte.MaxValue;
                    case "ui1":
                        return Byte.Parse(value) == Byte.MaxValue;
                    case "i2":
                        return Int16.Parse(value) == Int16.MaxValue;
                    case "ui2":
                        return UInt16.Parse(value) == UInt16.MaxValue;
                    case "int":
                    case "i4":
                        return Int32.Parse(value) == Int32.MaxValue;
                    case "ui4":
                        return UInt32.Parse(value) == UInt32.MaxValue;
                }
            }
            catch (OverflowException)
            {

            }
            catch (FormatException)
            {

            }

            return false;
        }

        #region UPnPType Method(s)

        public static Boolean IsUpnpType(String type)
        {
            switch (type)
            {
                case "string":
                case "boolean":
                case "i1":
                case "ui1":
                case "i2":
                case "ui2":
                case "i4":
                case "int":
                case "ui4":
                case "dateTime":
                    return true;
            }

            return false;
        }

        #endregion

        #region Constructor(s)
        internal UpnpDataType(String upnp)
        {
            Upnp = upnp;
        }
        #endregion
    }
}
